# -*- coding: utf-8 -*-
"""
  From http://pyedpypers.org/index.php?page=project&projectid=11&view=true, but modified to scale and speed
image = image.resize( (self.sizex, image.size[1] * self.sizex / image.size[0] ), Image.NEAREST)      # use nearest neighbour
"""
import PIL.Image as Image
import pygame
from pygame.locals import *

import time

class GIFImage(object):
  """
    This module is used for displaying gif images.
    filename: The filepath of the input image.
  """
  def __init__(self, filename):
    self.filename = filename
    self.image = Image.open(filename)
    self.frames = []
    self.get_frames()

    self.cur = 0
    self.ptime = time.time()

    self.running = True
    self.breakpoint = len(self.frames)-1
    self.startpoint = 0
    self.reversed = False

  def get_frames(self):
    image = self.image

    pal = image.getpalette()
    if pal is None:
      pal = image.convert("P", palette=Image.ADAPTIVE, colors=256).getpalette()
    base_palette = []
    for i in range(0, len(pal), 3):
      rgb = pal[i:i+3]
      base_palette.append(rgb)

    all_tiles = []
    try:
      while 1:
        if not image.tile:
          image.seek(0)
        if image.tile:
          all_tiles.append(image.tile[0][3][0])
        image.seek(image.tell()+1)
    except EOFError:
      image.seek(0)

    all_tiles = tuple(set(all_tiles))

    try:
      while 1:
        try:
          duration = image.info["duration"]
        except:
          duration = 100

        duration *= .001 #convert to milliseconds!
        cons = False

        x0, y0, x1, y1 = (0, 0) + image.size
        if image.tile:
          tile = image.tile
        else:
          image.seek(0)
          tile = image.tile
        if len(tile) > 0:
          x0, y0, x1, y1 = tile[0][1]

    ##                    if tile[0][3][0] in (4, 5):
    ##                        #replacement, don't have our own palette!
    ##                        palette = base_palette
    ##                    elif tile[0][3][0] in (6, 7):
    ##                        #consecutive blitting, have own palette's
    ##                        cons = True
    ##                        pal = image.getpalette()
    ##                        palette = []
    ##                        for i in range(0, len(pal), 3):
    ##                            rgb = pal[i:i+3]
    ##                            palette.append(rgb)
    ##                    else:
    ##                        pal = image.getpalette()
    ##                        palette = []
    ##                        for i in range(0, len(pal), 3):
    ##                            rgb = pal[i:i+3]
    ##                            palette.append(rgb)
    ##                else:
    ##                    palette = base_palette

        if all_tiles:
          if all_tiles in ((6,), (7,)):
            cons = True
            pal = image.getpalette()
            if pal is None:
              pal = image.convert("P", palette=Image.ADAPTIVE, colors=256).getpalette()
            palette = []
            for i in range(0, len(pal), 3):
              rgb = pal[i:i+3]
              palette.append(rgb)
          elif all_tiles in ((7, 8), (8, 7)):
            pal = image.getpalette()
            if pal is None:
              pal = image.convert("P", palette=Image.ADAPTIVE, colors=256).getpalette()
            palette = []
            for i in range(0, len(pal), 3):
              rgb = pal[i:i+3]
              palette.append(rgb)
          else:
            palette = base_palette
        else:
          palette = base_palette

    ##                try:
    ##                    if image.dispose:
    ##                        print "YAY!"
    ##                        i = image.dispose
    ##                        np = pygame.image.fromstring(i.tobytes(), i.size, i.mode)
    ##                        np.set_palette(palette)
    ##                        if "transparency" in i.info:
    ##                            np.set_colorkey(i.info["transparency"])
    ##                        cons = np
    ##                    else:
    ##                        print image.dispose
    ##                except:
    ##                    print image.dispose

        pi = pygame.image.fromstring(image.tobytes(), image.size, image.mode)
        try:
          pi.set_palette(palette)
        except:
          pass

        if "transparency" in image.info:
          pi.set_colorkey(image.info["transparency"])
        pi2 = pygame.Surface(image.size, SRCALPHA)
        if cons:
          for i in self.frames:
            pi2.blit(i[0], (0,0))
        pi2.blit(pi, (x0, y0), (x0, y0, x1-x0, y1-y0))

        self.frames.append([pi2, duration])
        image.seek(image.tell()+1)
    except EOFError:
      pass

  def render(self, screen, pos, size = None):
    if self.running:
      if time.time() - self.ptime > self.frames[self.cur][1]:
        if self.reversed:
          self.cur -= 1
          if self.cur < self.startpoint:
            self.cur = self.breakpoint
        else:
          self.cur += 1
          if self.cur >= self.breakpoint:
            self.cur = self.startpoint

        self.ptime = time.time()

    if size is not None:
      screen.blit(pygame.transform.scale(self.frames[self.cur][0], size), pos)
    else:
      screen.blit(self.frames[self.cur][0], pos)

  def seek(self, num):
    self.cur = num
    if self.cur < 0:
      self.cur = 0
    if self.cur >= len(self.frames):
      self.cur = len(self.frames)-1

  def set_bounds(self, start, end):
    if start < 0:
      start = 0
    if start >= len(self.frames):
      start = len(self.frames) - 1
    if end < 0:
      end = 0
    if end >= len(self.frames):
      end = len(self.frames) - 1
    if end < start:
      end = start
    self.startpoint = start
    self.breakpoint = end

  def pause(self):
    self.running = False

  def play(self):
    self.running = True

  def rewind(self):
    self.seek(0)
  def fastforward(self):
    self.seek(self.length()-1)

  def get_height(self):
    return self.image.size[1]
  def get_width(self):
    return self.image.size[0]
  def get_size(self):
    return self.image.size
  def length(self):
    return len(self.frames)
  def reverse(self):
    self.reversed = not self.reversed
  def reset(self):
    self.cur = 0
    self.ptime = time.time()
    self.reversed = False

  def copy(self):
    new = GIFImage(self.filename)
    new.running = self.running
    new.breakpoint = self.breakpoint
    new.startpoint = self.startpoint
    new.cur = self.cur
    new.ptime = self.ptime
    new.reversed = self.reversed
    return new

# def main():
#   pygame.init()
#   screen = pygame.display.set_mode((640, 480))

#   hulk = GIFImage("hulk.gif")
#   football = GIFImage("football.gif")
#   hulk2 = hulk.copy()
#   hulk2.reverse()
#   hulk3 = hulk.copy()
#   hulk3.set_bounds(0, 2)
#   spiderman = GIFImage("spiderman7.gif")

#   while 1:
#     for event in pygame.event.get():
#       if event.type == QUIT:
#         pygame.quit()
#         return

#     screen.fill((255,255,255))
#     hulk.render(screen, (50, 0))
#     hulk2.render(screen, (50, 150))
#     hulk3.render(screen, (50, 300))
#     football.render(screen, (200, 50))
#     spiderman.render(screen, (200, 150))
#     pygame.display.flip()

# if __name__ == "__main__":
#   main()
